package com.tnl.hunter.webchat.controller;

import com.biz.hunter.cache.EhCacheFactory;
import com.biz.hunter.dao.*;
import com.biz.hunter.db.entity.*;
import com.biz.qq.wechat.api.CustomerServiceMessageAPI;
import com.biz.system.config.SystemConfig;
import com.biz.system.config.WebchatServiceConstant;
import com.biz.wechat.api.media.Article;
import com.biz.wechat.api.msg.MessageUtil;
import com.biz.wechat.api.msg.resp.ResponseNewsMessage;
import com.biz.wechat.api.msg.resp.ResponseTextMessage;
import com.biz.wechat.util.SignUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.util.CollectionUtils;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Map;

@Controller
public class WebchatMainController {
	private static final Logger logger = LoggerFactory
			.getLogger(WebchatMainController.class);

	@Autowired
	private WXUserDAO userDAO;

	@Autowired
	private HunterDAO hunterDAO;
	
	@Autowired
	private EmployerDAO employerDAO;

	@Autowired
	private PageDAO pageDAO;
	
	@Autowired
	private JobDAO jobDAO;

	@Autowired
	private SysConfigRepo sysConfigRepo;

	@RequestMapping(value = "/WebChatMainService", method = RequestMethod.GET)
	public @ResponseBody String checkSignature(
			@RequestParam(value = "signature") String signature,
			@RequestParam(value = "timestamp") String timestamp,
			@RequestParam(value = "nonce") String nonce,
			@RequestParam(value = "echostr") String echostr) {
		String str = "";
		if (signature != null && timestamp != null && nonce != null
				&& echostr != null) {
			if (SignUtil.checkSignature(signature,WebchatServiceConstant.TOKEN,timestamp, nonce)) {
				str = echostr;
			}
		} else {
			str = "Sorry!";
		}

		logger.debug("return echostr is " + str);
		return str;
	}

	/**
	 * 
	 * @param request
	 * @param
	 * @return
	 */
	@RequestMapping(value = "/WebChatMainService", method = RequestMethod.POST, produces = "text/html;charset=UTF-8")
	public @ResponseBody String doPost(HttpServletRequest request) {
		// 解析XML消息
		Map<String, String> requestMap = MessageUtil.parseXml(request);
		if (CollectionUtils.isEmpty(requestMap)) {
			logger.error("the input request Map is empty");
			return "";
		}

		String fromUserName = requestMap.get("FromUserName");
		logger.info("xml openid="+fromUserName);

		// 进入消息/事件处理逻辑
		String respMessage = processRequest(requestMap);
		HttpSession session = request.getSession();
		session.setAttribute("OpenId", fromUserName);
		return respMessage;
	}

	public String processRequest(Map<String, String> requestMap) {
		String respMessage = "";

		String respContent = "请求处理异常，请稍候尝试！";

		String fromUserName = requestMap.get("FromUserName");
		String toUserName = requestMap.get("ToUserName");
		String msgType = requestMap.get("MsgType");

		respMessage = buildTextMsg(fromUserName, toUserName, respContent);

		if (msgType.equals(MessageUtil.REQ_MESSAGE_TYPE_TEXT)) {

			String rsqContent = requestMap.get("Content");
			logger.debug("text msg is" + rsqContent);

			respMessage = processTextMessage(fromUserName, toUserName,
					rsqContent);

		} else if (msgType.equals(MessageUtil.REQ_MESSAGE_TYPE_IMAGE)) {
			respContent = "您发送的是图片消息！";
			logger.warn(respContent);
			respMessage = buildCustomMsg(fromUserName, toUserName);
		} else if (msgType.equals(MessageUtil.REQ_MESSAGE_TYPE_LOCATION)) {
			respContent = "您发送的是地理位置消息！";
			logger.warn(respContent);
			respMessage = buildCustomMsg(fromUserName, toUserName);
		} else if (msgType.equals(MessageUtil.REQ_MESSAGE_TYPE_LINK)) {
			respContent = "您发送的是链接消息！";
			logger.warn(respContent);
			respMessage = buildCustomMsg(fromUserName, toUserName);
		} else if (msgType.equals(MessageUtil.REQ_MESSAGE_TYPE_VIDEO)) {
			respContent = "您发送的是视频消息！";
			logger.warn(respContent);
			respMessage = buildCustomMsg(fromUserName, toUserName);
		} else if (msgType.equals(MessageUtil.REQ_MESSAGE_TYPE_VOICE)) {
			if (requestMap.get("Recognition") != null) {
				respContent = "您发送的是语音识别后的消息！";
			} else {
				respContent = "您发送的是音频消息！";
			}
			logger.warn(respContent);
			respMessage = buildCustomMsg(fromUserName, toUserName);
		} else if (msgType.equals(MessageUtil.REQ_MESSAGE_TYPE_EVENT)) {
			//关注/取消关注事件
			String eventType = requestMap.get("Event");
			if (eventType.equals(MessageUtil.EVENT_TYPE_SUBSCRIBE)) {
				respMessage = subscribe(respMessage, fromUserName, toUserName);
				logger.info("新用户订阅 openId：  "+fromUserName+"  -----  msg:  "+ respMessage+"  ------ APPId：" +toUserName);
			} else if (eventType.equals(MessageUtil.EVENT_TYPE_UNSUBSCRIBE)) {

				unsubscribe(fromUserName);
				logger.info("用户取消订阅 openId：" + fromUserName);

				// respContent = "谢谢您取消关注！";
			} else if (eventType.equals(MessageUtil.EVENT_TYPE_SCAN)) {
				logger.warn("暂不支持SCAN");
				// respMessage = transferMsg(fromUserName, toUserName);

			} else if (eventType.equals(MessageUtil.EVENT_TYPE_GEO)) {
				logger.warn("暂不支持地理位置");
			} else if (eventType.equals(MessageUtil.EVENT_TYPE_CLICK)) {
				String eventKey = requestMap.get("EventKey");
				logger.debug("the menu click key is " + eventKey);
				if (eventKey.equalsIgnoreCase("xuanshangzhiwei")) {
					respMessage = buildNewsMsg(fromUserName, toUserName,
							PathEnum.hunter);
				}
				if (eventKey.equalsIgnoreCase("wodezhiwei")) {
					logger.debug("send out wodezhiwei");

					respMessage = buildNewsMsg(fromUserName, toUserName,
							PathEnum.employer);
				}
				if (eventKey.equalsIgnoreCase("lianxikefu")) {
					respMessage = buildTextMsg(fromUserName, toUserName,
							"请切换到键盘输入，直接给我们发微信，我们的客服会通过微信为您服务。");
				}
			}
		}
		return respMessage;
	}

	/**
	 * 如果是已填写直通车的用户，查看用户的关注公司和现任职位， 找到10条相关职位，推送图文新闻ResponseNewsMessage
	 * 
	 * @param fromUserName
	 * @param toUserName
	 * @param rsqContent
	 * @return
	 */
	private String processTextMessage(String fromUserName, String toUserName,
			String rsqContent) {
		String respMessage = "";
		String respContent;
		UserInfo userInfo = null;
		try {
			String token = sysConfigRepo.getAccessToken();
			userInfo = userDAO.subscribe(fromUserName,token);
		} catch (Exception e) {
			logger.error("subscribe and insert userinfo into DB", e);
		}
		if (userInfo == null) {
			logger.error("no subscriber info about " + fromUserName);
		}

		Hunter hunter = hunterDAO.getByActivateHunter(fromUserName);
		if (hunter == null) {
			logger.info("please goto the menu 'zhitongche' at first.");
			respContent = convertWelcomeMsg(fromUserName,
					userInfo.getNickname());
			respMessage = buildTextMsg(fromUserName, toUserName, respContent);
		}
		if (rsqContent.equalsIgnoreCase("m")) {
			logger.debug("send out the job list");
			respMessage = buildNewsMsg(fromUserName, toUserName,
					PathEnum.hunter);
		} else {
			logger.debug("the user input message is text other than 'M': "
					+ rsqContent);
			respMessage = buildTextMsg(fromUserName, toUserName,
					SystemConfig.getProperties("SubscribeResponse"));

			String token = sysConfigRepo.getAccessToken();
			// 客服接口回复 消息收到,尽快安排客服人员解答,
			CustomerServiceMessageAPI.sendTextMsg(fromUserName,
					SystemConfig.getProperties("SubscribeResponse"),token);

			// 转发消息给多客服
			respMessage = buildCustomMsg(fromUserName, toUserName);
		}
		return respMessage;
	}

	private String convertWelcomeMsg(String openId, String nickname) {
		String respContent = "sucess";
		logger.debug(" welcome " + nickname + "openid is" + openId);
		String MSG = SystemConfig.getProperties("SubscribeMSG");

		respContent = "Hi, " + nickname + "," + MSG ;
		logger.debug(" welcome msg is " + respContent);
		return respContent;
	}

	private String buildTextMsg(String fromUserName, String toUserName,
			String textMsg) {
		String respMessage = "";
		ResponseTextMessage rspMessage = new ResponseTextMessage();
		rspMessage.setToUserName(fromUserName);
		rspMessage.setFromUserName(toUserName);
		rspMessage.setCreateTime(new Date().getTime());
		rspMessage.setMsgType(MessageUtil.RESP_MESSAGE_TYPE_TEXT);
		rspMessage.setContent(textMsg);
		respMessage = MessageUtil.textMessageToXml(rspMessage);
		return respMessage;
	}

	private String buildCustomMsg(String fromUserName, String toUserName) {
		String respMessage = "";
		ResponseNewsMessage newsMessage = new ResponseNewsMessage();
		newsMessage.setToUserName(fromUserName);
		newsMessage.setFromUserName(toUserName);
		newsMessage.setCreateTime(new Date().getTime());
		newsMessage.setMsgType(MessageUtil.RESP_MESSAGE_TYPE_TRANSFER);

		respMessage = MessageUtil.newsMessageToXml(newsMessage);
		return respMessage;
	}

	private String buildNewsMsg(String fromUserName, String toUserName,
			PathEnum path) {

		String respMessage = "";
		ResponseNewsMessage newsMessage = new ResponseNewsMessage();
		newsMessage.setToUserName(fromUserName);
		newsMessage.setFromUserName(toUserName);
		newsMessage.setCreateTime(new Date().getTime());
		newsMessage.setMsgType(MessageUtil.RESP_MESSAGE_TYPE_NEWS);

		List<Article> articles = new ArrayList<Article>();

		// platform, domain, path, start, end
		String openId = fromUserName;
		List<JobDesc> jobs = findJobs(path, openId);
		if (jobs == null || jobs.size() == 0) {
			logger.error("can not get the jobs list");
			//暂时没有新的职位，如果继续点击菜单，将重新从第一页获取职位信息
			respMessage = buildTextMsg(fromUserName,toUserName,
					"暂时没有新的职位，继续点击\"悬赏职位\"菜单，将重新从第一页获取职位信息");
			return respMessage;
		}

		boolean isFirst = true;
		newsMessage.setArticleCount(jobs.size());
		for (JobDesc jd : jobs) {
			Article article = new Article();
			article.setTitle(jd.getName());
			String domain = SystemConfig.getProperties("Domain");
			article.setUrl("http://" + domain
					+ "/tnl-hunter/wechat/headhunter/jobdetail.page?id=" + jd.getId());
			if (isFirst) {

				article.setPicUrl("http://" + domain
						+ "/tnl-hunter/resources/images/img15.jpg");
			} else {

				article.setPicUrl("http://" + domain
						+ "/tnl-hunter/resources/images/img1.jpg");
			}
			isFirst = false;
			article.setDescription(jd.getDescription());
			articles.add(article);
		}
		newsMessage.setArticles(articles);
		respMessage = MessageUtil.newsMessageToXml(newsMessage);
		logger.debug("News Message is " + respMessage);
		return respMessage;
	}

	private List<JobDesc> findJobs(PathEnum path, String openId) {
		List<JobDesc> jobs = null;
		Hunter hunter = hunterDAO.getByActivateHunter(openId);
		List<Integer> domains = new ArrayList<>();
		if(hunter.getMajordomain1() != 0){
			domains.add(hunter.getMajordomain1());
		}
		if(hunter.getMajordomain2() != 0){
			domains.add(hunter.getMajordomain2());
		}
		if(hunter.getMajordomain3() != 0){
			domains.add(hunter.getMajordomain3());
		}
		if (hunter == null) {
			logger.error("there is no hunter with the openid " + openId);
			return null;
		}

		Integer offset = 0;
		int pageNum = 0;
		Date todayDate = new Date();
		long today = todayDate.getTime();
		long total =  jobDAO.countRecommendJobs4Hunter(today,domains);
		logger.debug(" there are "+ total +" jobs ");
		pageNum = findCurrentPage(openId);
		if(pageNum * JobDAO.PAGE_SIZE < total){
			//pageNum += 1;
			//save it
			this.resetPage(openId, pageNum+1);
			offset = JobDAO.PAGE_SIZE * pageNum;
			logger.debug("pageNum is "+ pageNum);
			
			jobs = jobDAO.searchRecommendJobs4Hunter2(offset,JobDAO.PAGE_SIZE, today,domains);
			logger.debug("jobs list is "+ jobs);
			
			return jobs;
		}
		else{
			//reset the page number
			this.resetPage(openId, 0);
			logger.info("the last page, reset the pagenumb" );
			return null;
		}
		
	}

	private int findCurrentPage(String openId) {
	  int currentpageNum = 0;
		int platformId = PlatformEnum.Hunting.getValue();
		Page page = pageDAO.getByOpenId(openId,platformId);
		logger.debug("get page info"+ page);
		if (page != null) {
			 currentpageNum = page.getPageNum();
			 //page.setPageNum(currentpageNum + 1);
			//pageDAO.update(page);
		}
		return currentpageNum;
	}
	private int resetPage(String openId, int pageNum) {
		int platformId = PlatformEnum.Hunting.getValue();
		Page page = pageDAO.getByOpenId(openId,platformId);
		logger.debug("get page info"+ page);
		if (page != null) {
			page.setPageNum(pageNum);
			return pageDAO.update(page);
		} else {
			Page newPage = new Page();
			newPage.setPlatformId(platformId);
			newPage.setOpenId(openId);
			newPage.setPageNum(pageNum);
			return pageDAO.save(newPage);
		}
		//return pageNum;
	}
	private void unsubscribe(String fromUserName) {
		logger.info("unsubscribe remove tokenkey="+sysConfigRepo.getTokenKey());
		EhCacheFactory.delete(sysConfigRepo.getTokenKey());
		int result = userDAO.unSubscribe(fromUserName);
		Hunter hunter = hunterDAO.getByActivateHunter(fromUserName);
		if (hunter!=null)
		{
			logger.info("there is no employee registed.");
			hunter.setActive(Employee.inactivate);
			result = hunterDAO.deactivate(hunter);
		}
		
		Employer hr = employerDAO.getByOpenId(fromUserName);
		if (hr!=null)
		{
			logger.info("there is no employee registed.");
			hr.setActive(Employee.inactivate);
			result = employerDAO.update(hr);
		}
		
		
		logger.info("unsubscribe() return value is " + result);
	}

	private String subscribe(String respMessage, String fromUserName,
			String toUserName) {
		String respContent;
		UserInfo userInfo = null;
		try {
			String token = sysConfigRepo.getAccessToken();
			userInfo = userDAO.subscribe(fromUserName,token);
		} catch (Exception e) {
			logger.error("subscribe and insert userinfo into DB", e);
		}
		
		if (userInfo != null) {
			Hunter hunter = hunterDAO.getByOpenId(fromUserName,Hunter.inactivate);
			if (hunter!=null)
			{
				logger.info("there is no employee registed.");
				hunter.setActive(Employee.activate);
				 hunterDAO.activate(hunter);
			}
			
			Employer hr = employerDAO.getByOpenId(fromUserName,Employer.inactivate);
			if (hr!=null)
			{
				logger.info("there is no employee registed.");
				hr.setActive(Employee.activate);
				 employerDAO.update(hr);
			}
			respContent = convertWelcomeMsg(fromUserName,
					userInfo.getNickname());
			respMessage = buildTextMsg(fromUserName, toUserName,
					respContent);
		} else {
			logger.error("DAO insert Userinfo failed. ");
		}
		return respMessage;
	}
}
